﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace CountdownTool
{
    /// <summary>
    /// TimeShow.xaml 的交互逻辑
    /// </summary>
    public partial class TimeShow : Window
    {
        public SettingViewModel Setting { get; private set; }
        public bool IsRunning { get; private set; }


        private readonly Countdown _countdown;


        public TimeShow(SettingViewModel setting)
        {
            InitializeComponent();
            this.ShowInTaskbar = false;

            Setting = setting ?? throw new NullReferenceException(nameof(setting));
            this.DataContext = setting;
            _countdown = new Countdown(Setting);
            _countdown.CountdownToZero += CountdownOnCountdownToZero;
            _countdown.ReportInvervalElapsed += CountdownOnReportInvervalElapsed;
            _countdown.ReportLastOneMinute += CountdownOnReportLastOneMinute;

            Setting.Reset();

            this.Top = -Height;

        }

        private void CountdownOnReportLastOneMinute(object o, EventArgs eventArgs)
        {
            this.Dispatcher.InvokeAsync(ShowWithAnimation);
        }

        private void CountdownOnReportInvervalElapsed(object o, EventArgs eventArgs)
        {
            this.Dispatcher.InvokeAsync(ShowInShortTime);
        }

        public void ShowInShortTime()
        {
            if (Setting.IsHoldOn || Setting.IsOverZero)
            {
                ShowWithAnimation();
                return;
            }
            if (Setting.CurrentMuniteValue < Countdown.LastMinuteThreshold)
            {
                ShowWithAnimation();
                return;
            }

            Timer timer = new Timer(12000);
            ShowWithAnimation();
            timer.Elapsed += TimerOnElapsed;
            timer.Start();

            void TimerOnElapsed(object obj, ElapsedEventArgs elapsedEventArgs)
            {
                timer.Stop();
                timer.Elapsed -= TimerOnElapsed;
                this.Dispatcher.InvokeAsync(HideWithAnimation);
            }
        }



        private void CountdownOnCountdownToZero(object sender, EventArgs eventArgs)
        {
            Setting.IsOverZero = true;
            this.Dispatcher.InvokeAsync(ShowWithAnimation);
        }


        public void StartCountdown()
        {
            _countdown.Start();
            ShowInShortTime();
            IsRunning = true;
            _countdown.ReportInverval = Setting.IntervalValue * 60;
        }

        public void ResetCountdown()
        {
            _countdown.Stop();
            Setting.Reset();
            IsRunning = false;
        }

        public void StopCountdown()
        {
            _countdown.Stop();
            HideWithAnimation();
            IsRunning = false;
        }

        public void ShowWithAnimation()
        {
            if (this.Top >= 0)
            {
                return;
            }

            var workAreaWidth = SystemParameters.WorkArea.Width;
            var workAreaHeight = SystemParameters.WorkArea.Height;
            double startY = 0;
            double endY = 0;
            double leftLocation;
            switch (Setting.TimeWindowLocation)
            {
                case TimeWindowLocation.LeftUp:
                    leftLocation = 10;
                    break;
                case TimeWindowLocation.RightUp:
                default:
                    leftLocation = workAreaWidth - Width - 10;
                    break;
            }

            startY = -Height;
            endY = 0;
            this.Left = leftLocation;
            this.Top = startY;

            this.Show();
            this.Topmost = true;

            DoubleAnimation animation = new DoubleAnimation(startY, endY, new Duration(TimeSpan.FromSeconds(1)));
            this.BeginAnimation(TopProperty, animation);
        }

        public void HideWithAnimation()
        {
            if (this.Top < 0)
            {
                return;
            }

            double startY = this.Top;
            double endY = -this.Height;

            DoubleAnimation animation = new DoubleAnimation(startY, endY, new Duration(TimeSpan.FromSeconds(1)));
            this.BeginAnimation(TopProperty, animation);

            void Complected(object sender, EventArgs args)
            {
                this.Hide();
                this.Topmost = false;
                animation.Completed -= Complected;
            }

            animation.Completed += Complected;
        }

        public void ShowOnLeftOrRight()
        {
            var workAreaWidth = SystemParameters.WorkArea.Width;
            double leftLocation;
            switch (Setting.TimeWindowLocation)
            {
                case TimeWindowLocation.LeftUp:
                    leftLocation = 10;
                    break;
                case TimeWindowLocation.RightUp:
                default:
                    leftLocation = workAreaWidth - Width - 10;
                    break;
            }
            this.Left = leftLocation;
        }

    }


    public enum TimeWindowLocation
    {
        RightUp,
        LeftUp,
    }

    public class BoolToBrushConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool isOverZero)
            {
                if (!isOverZero)
                {
                    return new SolidColorBrush(Colors.DarkOrange);
                }
                else
                {
                    return new SolidColorBrush(Colors.Red);
                }
            }
            return new SolidColorBrush(Colors.DarkOrange);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool b)
            {
                if (b)
                {
                    return Visibility.Visible;
                }
                else
                {
                    return Visibility.Collapsed;
                }
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

}
